﻿using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Interop;
using System.Threading;
using System.Windows.Threading;
using System.Collections.Generic;
using MovieInfoSearchLib;
using System.Reflection;
using System.Windows.Interop;
using System.Runtime.InteropServices;
using System.Threading;
using MovieInfo;

namespace MovieTagger
{
	public partial class MainWindow
	{
        //A variable to hold the queued files
        private List<string> fileQueue = new List<string>();

        private List<MovieSearch> SearchQueue = new List<MovieSearch>();

        private List<Movie> DataQueue = new List<Movie>();

        private bool queueFinished = false;

        private MovieSearch ms = null;
        public MainWindow()
		{
			this.InitializeComponent();
			
			// Insert code required on object creation below this point.
		}

        /// <summary>
        /// This function plays the given animation
        /// </summary>
        /// <param name="anim">The name of the animation to play</param>
        private void _animPlay(string anim)
        {
                ThreadStart start = delegate()
                {
                    try
                    {
                       
                        this.Dispatcher.Invoke(DispatcherPriority.Normal,
                                new Action<string>(_animWorker), anim);

                       
                    }
                    catch (TargetInvocationException e)
                    {
                        MessageBox.Show(e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);

                    }

                };

                new Thread(start).Start();

        }

        private void _animWorker(string anim)
        {
            Storyboard a = (Storyboard)FindResource(anim);
            a.Begin();

        }

        public void addFile(string filename)
        {
            if (filename.Contains(".mp4") || filename.Contains(".m4v"))
            {
                if (SearchQueue.Count > 0)
                {
                    MovieSearch tmpSearch = new MovieSearch(filename, null);
                    tmpSearch.SearchAsync();

                    SearchQueue.Add(tmpSearch);
                }

                    //this is the first file added to the queue
                else
                {
                    MovieSearch tmpSearch = new MovieSearch(filename, null);
                    

                    _animPlay("GotoStatus");
                    tmpSearch.setProgress = new MovieSearch.SetProgressCallback(setProgressValue);
                    tmpSearch.setStatus = new MovieSearch.SetStatusCallback(setStatusText);
                    tmpSearch.callback = new MovieSearch.MovieResultsCallback(_movieResults);
                    tmpSearch.SearchAsync();
                    SearchQueue.Add(tmpSearch);

                    this.Title = "Movie Tagger - " + SearchQueue[0].query;
                }
            }
        }

        private void _searchNext()
        {
            //TODO: Download images before showing the results
            if (SearchQueue.Count > 0)
            {
                this.Title = "Movie Tagger - " + SearchQueue[0].query;


                if (!SearchQueue[0].SearchComplete)
                {
                    _animPlay("GotoStatus");
                    SearchQueue[0].setProgress = new MovieSearch.SetProgressCallback(setProgressValue);
                    SearchQueue[0].setStatus = new MovieSearch.SetStatusCallback(setStatusText);
                    SearchQueue[0].callback = new MovieSearch.MovieResultsCallback(_movieResults);
                }
                else
                    _movieResults();
            }
            else
            {
                queueFinished = true;
                if(DataQueue.Count > 0)
                    _animPlay("GotoStatus");
            }
        }

        

        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            base.OnRenderSizeChanged(sizeInfo);

            double sHeight = System.Windows.SystemParameters.PrimaryScreenHeight;

            sHeight /= 2;
            sHeight -= this.Height / 2;

            this.Top = sHeight;
        }


        private void _movieResults()
        {

            if (SearchQueue[0].results != null)
            {
                _animPlay("GotoStatus");
                this.setStatusText("Downloading images...");
                this.setProgressValue(0);
                CtrlSelect.OnSelectionChanged += new EventHandler(CtrlSelect_OnSelectionChanged);
                CtrlSelect.OnFinishedLoading += new EventHandler(CtrlSelect_OnFinishedLoading);
                CtrlSelect.OnDownloadProgressChanged += new EventHandler(CtrlSelect_OnDownloadProgressChanged);
                CtrlSelect.initData(SearchQueue[0].results);
            }
            else
            {
                SearchQueue.RemoveAt(0);
                _searchNext();
            }
        }

        void CtrlSelect_OnDownloadProgressChanged(object sender, EventArgs e)
        {
            this.setProgressValue(CtrlSelect.getProgress());
        }

        void CtrlSelect_OnFinishedLoading(object sender, EventArgs e)
        {
            _animPlay("GotoResults");
            
            this.setProgressValue(0);
        }

        void CtrlSelect_OnSelectionChanged(object sender, EventArgs e)
        {
            CtrlInfo.ViewMovieInfo(CtrlSelect.SelectedMovie);
        }

        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            base.OnClosing(e);
        }

        #region statusFunctions
        public void setStatusText(string newStatus)
        {
            ThreadStart setText = delegate()
            {
                Dispatcher.Invoke(DispatcherPriority.Normal,
                    new Action<string>(_setStatusText), newStatus);

            };

            new Thread(setText).Start();
        }


        private void _setStatusText(string newStatus)
        {
            this.txtStatus.Text = newStatus;
        }


        public void setProgressValue(int progress)
        {
            ThreadStart setProgress = delegate()
            {
                Dispatcher.Invoke(DispatcherPriority.Normal,
                    new Action<int>(_setProgressValue), progress);

            };

            new Thread(setProgress).Start();
        }

        private void _setProgressValue(int progress)
        {
            this.progMainProgress.Value = progress;
        }

        public void stopApp()
        {
            ThreadStart setText = delegate()
            {
                Dispatcher.Invoke(DispatcherPriority.Normal,
                    new Action(_stopApp));

            };

            new Thread(setText).Start();
        }


        private void _stopApp()
        {
            Application.Current.Shutdown();
        }
        #endregion

        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);

            HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
            source.AddHook(WndProc);
        }

        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            switch (msg)
            {
                case MessageHelper.WM_COPYDATA:
                    MessageHelper.COPYDATASTRUCT mystr = (MessageHelper.COPYDATASTRUCT)Marshal.PtrToStructure(lParam, typeof(MessageHelper.COPYDATASTRUCT));

                    this.addFile(mystr.lpData);
                    break;
            }

            return IntPtr.Zero;
        }

        private void _setDataProgress(int progress)
        {
            if (queueFinished)
            {
                this.setStatusText("Setting data for " + DataQueue[0].title + "...");
                this.setProgressValue(DataQueue[0]._getProgress());
            }
        }

        private void _onMovieFinished(Movie target)
        {
            this.DataQueue.Remove(target);


            //all data has been set
            if (this.DataQueue.Count == 0 &&
               this.fileQueue.Count == 0)
                stopApp();
        }

        public override void EndInit()
        {
            base.EndInit();
            _animPlay("GotoResults");
        }

        private void btnSetData_Click(object sender, RoutedEventArgs e)
        {
            CtrlSelect.SelectedMovie._setProgress = new MovieSearch.SetProgressCallback(_setDataProgress);
            CtrlSelect.SelectedMovie._onFinished = new MovieSearch.SetDataFinished(_onMovieFinished);
            CtrlSelect.setSelectedMovieImage();
            CtrlSelect.SelectedMovie.writeMetaData(SearchQueue[0].Filename);
            this.DataQueue.Add(CtrlSelect.SelectedMovie);


            SearchQueue.RemoveAt(0);
            CtrlSelect.clear();
            CtrlInfo.Clear();
            this._searchNext();
        }
    }
}